package com.sisgh.jefdv1.core.jdbc.table;

import com.mysql.cj.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 表工具类
 */
@Slf4j
public class Tables {

    private static final String[] TYPES = {"TABLE"};

    /**
     * 从连接中获取表信息
     * @param conn
     * @param database
     * @return
     * @throws SQLException
     */
    private static List<Table> doFetchTables (Connection conn, String database) throws SQLException {
        log.info("拉取数据表数据");

        DatabaseMetaData metaData = conn.getMetaData();

        ResultSet rs = metaData.getTables(database, null, null, TYPES);

        log.info("创建 Table 集合");
        List<Table> tables = new ArrayList<>();
        while (rs.next()) {
            String tableName = rs.getString(Table.NAME);

            Table table = new Table();
            table.setName(tableName);

            List<Column> columns = doBuildColumns(metaData, database, tableName);
            if (columns.isEmpty()) {
                // logger
                log.error("表 {} 不存在相应的列", tableName);
                continue;
            }

            table.setColumns(columns);

            tables.add(table);
        }

        return tables;
    }

    /**
     * 将获取的表数据转换成 Column 集合
     * @param metaData
     * @param database
     * @param table
     * @return
     * @throws SQLException
     */
    private static List<Column> doBuildColumns (DatabaseMetaData metaData, String database, String table) throws SQLException {
        ResultSet columns = metaData.getColumns(database, null, table, null);
        List<Column> columnList = new ArrayList<>();

        while (columns.next()) {
            String name = columns.getString(Column.NAME);
            String type = columns.getString(Column.TYPE);

            columnList.add(new Column(name, type));
        }

        return columnList;
    }

    /**
     * 抽取表数据，用于外部
     * @param conn
     * @param database
     * @return
     * @throws SQLException
     */
    public static List<Table> fetchTables(Connection conn, String database) throws SQLException{
        if (Objects.isNull(conn)) {
            throw new SQLException("conn is null");
        }

        if (StringUtils.isEmptyOrWhitespaceOnly(database)) {
            throw new SQLException("database is invalid");
        }

        return doFetchTables(conn, database);
    }

    /**
     * 抽取表数据，用于外部
     * @param conn
     * @return
     * @throws SQLException
     */
    public static List<Table> fetchTables(Connection conn) throws SQLException {
        if (Objects.isNull(conn)) {
            log.error("Connection 实例为 null");

            throw new SQLException("conn is null");
        }

        String database = conn.getCatalog();
        if (StringUtils.isNullOrEmpty(database)) {
            log.error("Connection 未指定数据库");

            throw new SQLException("database name is isEmpty");
        }

        return doFetchTables(conn, database);
    }
}
